require_relative 'treasure'
require_relative 'treasure_kind'
require_relative 'bad_stuff'
require_relative 'monster'
require_relative 'dice'

module Napakalaki

  class Player
    
    attr_reader :dead, :name, :level, :hidden_treasures, :visible_treasures, :pending_bad_stuff
              
    def initialize (dead, name, level, hidden, visible, bad)
      @dead = dead
      @name = name
      @level = level
      @hidden_treasures = hidden
      @visible_treasures = visible    
      @pending_bad_stuff = bad
    end
    
    #CONSTRUCTOR Que recibe un string
    def self.new_name(name) 
      self.new(true, name, 1, Array.new, Array.new, BadStuff.new_death("", true))
    end 
    
    def self.new_copy(player)    #constructor de copia
      @dead = player.dead
      @name = String.new(player.name)
      @level = player.level
      @hidden_treasures = Array.new(player.hidden_treasures)
      @visible_treasures = Array.new(player.visible_treasures)
      @pending_bad_stuff.equal(player.pending_bad_stuff)
    end
    
    private #son métodos privados hasta que se diga lo contrario    
    def bring_to_life
      @dead = false
    end
    
    def get_combat_level
      min_bonus = 0
      max_bonus = 0
      tengo_collar = 0
      nivel_total = @level
      for v in visible_treasures
        min_bonus += v.min_bonus
        max_bonus += v.max_bonus
        if v.type == :NECKLACE
          ++tengo_collar
        end       
      end      
      if tengo_collar > 0
        nivel_total += max_bonus
      else
        nivel_total += min_bonus
      end      
      return nivel_total
    end
    
    def increment_levels(l)
      @level += l
    end    

    def decrement_levels(l)
      @level -= l
      if @level < 1
        @level = 1
      end
    end    
    
    def set_pending_bad_stuff(b)
      @pending_bad_stuff = b
    end    
    
    def die_if_no_treasures
      if visible_treasures.empty? && hidden_treasures.empty?
        @dead = true
      end     
    end    
    
    def discard_necklace_if_visible
      if @visible_treasures.include?(:NECKLACE)
        CardDealer.instance.give_treasure_back(v)
        self.discard_visible_treasures(:NECKLACE)
      end
    end   
    
    def die
      @level = 1
      dealer = CardDealer.instance

      for treasure in @visible_treasures
        dealer.give_treasure_back(treasure)
      end
      @visible_treasures.clear()      
      for treasure in @hidden_treasures
        dealer.give_treasure_back(treasure)        
      end      
      @hidden_treasures.clear()      
      die_if_no_treasures()          
    end      
    
    def compute_gold_coins_value(t)
      if(t==nil || t.size == 0)
        return 0;
      else
        numero = 0
        for tesoros in t
          numero += tesoros.gold_coins
        end      
        return numero/1000
      end            
    end    
    
    def can_i_buy_levels(l)      
      if (level + l >= 10)
        return false
      else
        return true
      end      
    end    
    
    def apply_prize(current_monster)
      levels_ganados = current_monster.get_levels_gained()
      increment_levels(levels_ganados)
      n_treasures = current_monster.get_treasures_gained()
      if (n_treasures > 0)
        dealer = CardDealer.instance
        (1..n_treasures).each do          
          treasure = dealer.next_treasure()
          @hidden_treasures << treasure
        end
      end      
    end  
   
    
    def apply_bad_stuff(bad)
      n_levels = bad.levels;
      decrement_levels(n_levels)
      @pending_bad_stuff = bad.adjust_to_fit_treasure_lists(@visible_treasures, @hidden_treasures)      
    end
    
    def can_make_treasure_visible(t)
      puedo = true
      numero_armas_una_mano = 0
            
      for v in visible_treasures
        
        if (puedo == false)
          return false
        else
          
          #si es de tipo armor, helmet, necklace o shoe, y además está equipado no se puede hacer visible
          if ((t.type == :ARMOR || t.type == :HELMET || t.type == :NECKLACE || t.type == :SHOE) && t.type == v.type)
            puedo = false
          end
          
          #si es de tipo 2 manos y tengo algo equipado en las manos, no puedo hacerlo visible
          if (t.type == :BOTHHAND && (v.type == :BOTHHAND || v.type == :ONEHAND)) 
            puedo = false
          end
          
          #si es de 1 mano y tengo algo de 2 manos, no puedo hacerlo visible
          if (t.type == :ONEHAND && v.type == :BOTHHAND)
            puedo = false
          end
          
          #cuento las armas de 1 mano que tengo
          if (v.type == :ONEHAND)
            ++numero_armas_una_mano
          end
          
        end  
          
      end
      
      if (t.type == :ONEHAND && numero_armas_una_mano > 1)
        puedo = false
      end
      
      return puedo
      
    end

    
    def how_many_visible_treasures(t_kind)
      numero = 0
      
      for t in @visible_treasures
        if visible_treasures.type == t_kind
          ++numero
        end
      end
      
      return numero
    end
    
    
    public #métodos públicos ######################
    
    
    def is_dead
      return @dead
    end

    
    def combat(m)
      my_level = get_combat_level
      monster_level = m.combat_level
      combat_result = nil
      if my_level > monster_level
        apply_prize(m)
        if @level >= 10
          combat_result = :WINANDWINGAME
        else
          combat_result = :WIN
        end
      else
        escape = Dice.instance.next_number
        if escape < 5
          am_i_dead = m.kills
          if am_i_dead
            die
            combat_result = :LOSEANDDIE
          else
            apply_bad_stuff(m.bad_stuff)
            combat_result = :LOSE
          end          
        else
          combat_result = :LOSEANDSCAPE
        end
      end
      
      discard_necklace_if_visible
      
      return combat_result
    end
    
    
    def make_treasure_visible(t)
      if can_make_treasure_visible(t)
        @visible_treasures << t
        @hidden_treasures.delete(t)
      end
    end

    
    def discard_visible_treasure(t)
      @visible_treasures.delete(t)
      if @pending_bad_stuff != nil && !@pending_bad_stuff.is_empty
        @pending_bad_stuff.substract_visible_treasure(t)
      end
      die_if_no_treasures
    end
    
    
    def discard_hidden_treasure(t)
      @hidden_treasures.delete(t)
      if @pending_bud_stuff != nil && !@pending_bad_stuff.is_empty
        @pending_bud_stuff.substract_hidden_treasure(t)
      end
      die_if_no_treasures      
    end
    
    
    def buy_levels(visible, hidden)
      levels_may_bought = compute_gold_coins_value(visible)
      levels_may_bought += compute_gold_coins_value(hidden)
      can_i = can_i_buy_levels(levels_may_bought) 
      if can_i
        increment_levels(levels_may_bought)
      end

      dealer = CardDealer.instance
      for t_v in visible
        dealer.give_treasure_back(t_v)
        @visible_treasures.delete(t_v)
      end
      for t_h in hidden
        dealer.give_treasure_back(t_h)
        @hidden_treasures.delete(t_h)
      end
      return can_i
    end    
    
    def valid_state      
      return (@pending_bad_stuff.is_empty && @hidden_treasures.size <= 4)  
    end   
    
    def init_treasures
      dealer = CardDealer.instance
      dice = Dice.instance
      bring_to_life
      @hidden_treasures << dealer.next_treasure
      num = dice.next_number
      if num > 1
        @hidden_treasures << dealer.next_treasure
      end
      if num == 6
        @hidden_treasures << dealer.next_treasure
      end
    end
    
    def has_visible_treasures 
      return !visible_treasures.empty?  
    end
  
    def should_convert()
      if (Dice.instance.nextNumber() == 6)
        return true
      else
        return false
      end
    end
    
    def get_oponent_level(m)
      return m.get_basic_value
    end
  end  
end
